package cn.com.libertymutual.saleplat.config;

import java.util.Collections;
import java.util.List;

import javax.annotation.Resource;
import javax.naming.directory.DirContext;

import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.AbstractContextMapper;
import org.springframework.ldap.core.support.LdapContextSource;
import org.springframework.ldap.filter.AndFilter;
import org.springframework.ldap.filter.EqualsFilter;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.ldap.LdapUtils;
import org.springframework.stereotype.Component;

import com.google.common.base.Throwables;

import cn.com.libertymutual.core.security.encoder.Md5PwdEncoder;
import cn.com.libertymutual.core.security.ldap.LdapExceptionUtil;
import cn.com.libertymutual.sys.bean.SysUser;
import cn.com.libertymutual.sys.dao.ISysUserDao;
import cn.com.libertymutual.sys.ldap.Person;
import cn.com.libertymutual.sys.ldap.PersonAttributeMapper;

@Component
public class LadpAuthProvider implements AuthenticationProvider {
	private Logger log = LoggerFactory.getLogger(LadpAuthProvider.class);

	/// @Resource private PwdEncoder pwdEncoder;

	/// @Resource
	private LdapTemplate ldapTemplate;
	// @Resource private ILdapService adServiceImpl;
	@Resource
	private ContextSource contextSource;
	@Autowired
	private ISysUserDao iSysUserDao;

	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
		// log.debug("自定义provider调用");
		// BadCredentialsException
		// log.info(authentication.getName());
		// log.info(authentication.getCredentials().toString());
		SysUser oldUser = iSysUserDao.findByUserid(authentication.getName());
		if (null == oldUser) {
			List<SysUser> oldUsers = iSysUserDao.findByMobile(authentication.getName());
			if (CollectionUtils.isNotEmpty(oldUsers)) {
				if (oldUsers.size() != 1) {
					Throwables.propagate(new BadCredentialsException("存在多个手机号为[" + authentication.getName() + "]的用户"));
				}
				SysUser sysUser = oldUsers.get(0);
				// 校验密码
				Md5PwdEncoder md5PwdEncoder = new Md5PwdEncoder();
				if (!md5PwdEncoder.isPasswordValid(sysUser.getPassword(), authentication.getCredentials().toString())) {
					Throwables.propagate(new BadCredentialsException("用户名或密码错误"));
				} else {
					return new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(),
							Collections.<GrantedAuthority>emptyList());
				}
			}else{
				Throwables.propagate(new BadCredentialsException("用户名或密码错误!"));
			}
		}else{
			Md5PwdEncoder md5PwdEncoder = new Md5PwdEncoder();
			if (!md5PwdEncoder.isPasswordValid(oldUser.getPassword(), authentication.getCredentials().toString())) {
				Throwables.propagate(new BadCredentialsException("用户名或密码错误"));
			} else {
				return new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(),
						Collections.<GrantedAuthority>emptyList());
			}
		}
		/*
		 * TpAccount tp = TpAccountUtil.getAccountFromRedis( authentication.getName() );
		 * if( !TpAccountUtil.checkAccount( tp ) ) throw new
		 * BadClientCredentialsException();
		 * 
		 * 
		 * if( !pwdEncoder.isPasswordValid( (String)authentication.getCredentials(),
		 * tp.getPartnerAccountCode() + "|" + tp.getClientId(), tp.getPasskey() ) ) {
		 * throw new BadClientCredentialsException(); }
		 */
		// Md5PwdEncoder md5PwdEncoder = new Md5PwdEncoder();
		// List<String> results = null;
		// if (!md5PwdEncoder.isPasswordValid(oldUser.getPassword(),
		// authentication.getCredentials().toString())) {
		// AndFilter filter = new AndFilter();
		// filter.and(new EqualsFilter("objectclass", "person")).and(new
		// EqualsFilter("sAMAccountName", (String) authentication.getPrincipal()));
		// results = ldapTemplate.search("", filter.encode(), new DnContextMapper());
		// if (results.size() != 1) {
		// Throwables.propagate(new BadCredentialsException("用户名或密码错误"));
		// }
		// } else {
		// return new UsernamePasswordAuthenticationToken(authentication.getPrincipal(),
		// authentication.getCredentials(),
		// Collections.<GrantedAuthority>emptyList());
		// }
		//
		// DirContext ctx = null;
		// try {
		// ctx = contextSource.getContext(results.get(0), (String)
		// authentication.getCredentials());
		// } catch (Exception e) {
		// log.error(e.getMessage());
		// Throwables.propagate(new BadCredentialsException(new
		// LdapExceptionUtil(e).getErrorMessage(), e));
		// } finally {
		// LdapUtils.closeContext(ctx);
		// }
		// 返回一个Token对象表示登陆成功
		return new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(),
				Collections.<GrantedAuthority>emptyList());
	}

	@Bean
	@ConfigurationProperties(prefix = "ldap.context-source")
	public LdapContextSource contextSource() {
		LdapContextSource ldapContextSource = new LdapContextSource();
		/*
		 * ldapContextSource.setUrl(URL); ldapContextSource.setBase(DOMAIN);
		 * ldapContextSource.setUserDn(""); //ldapContextSource.setPassword("");
		 * ldapContextSource.setReferral("follow");
		 */
		return ldapContextSource;
	}

	@Bean
	public LdapTemplate ldapTemplate(LdapContextSource ldapContextSource) {
		// LdapTemplate lt = new LdapTemplate( ldapContextSource );

		ldapTemplate = new LdapTemplate(ldapContextSource);

		return ldapTemplate;
	}

	private final static class DnContextMapper extends AbstractContextMapper<String> {

		@Override
		protected String doMapFromContext(DirContextOperations ctx) {
			// TODO Auto-generated method stub
			return ctx.getNameInNamespace();
		}

	}

	@Override
	public boolean supports(Class<?> aClass) {
		return true;
	}
}